package com.vcg.community.common.utils;

import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.CtField;
import javassist.CtNewMethod;
import javassist.NotFoundException;

import org.apache.commons.beanutils.BeanUtils;

/**
 * class 工具类
 * @author 19128_000
 *
 */
class ClassUtils {
	
	
	
	// 给一个接口，返回这个接口的所有实现类
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static List<Class> getAllClassByInterface(Class c) throws Exception {
		List<Class> returnClassList = new ArrayList<Class>(); // 返回结果
		// 如果不是一个接口，则不做处理
		if (c.isInterface()) {
			String packageName = c.getPackage().getName(); // 获得当前的包名
			List<Class> allClass = getClasses(packageName);
			// 判断是否是同一个接口
			for (int i = 0; i < allClass.size(); i++) {
				if (c.isAssignableFrom(allClass.get(i))) { // 判断是不是一个接口
					if (!c.equals(allClass.get(i))) { // 本身不加进去
						returnClassList.add(allClass.get(i));
					}
				}
			}
		}
		return returnClassList;
	}

	@SuppressWarnings("rawtypes")
	public static List<Class> getClasses(String packageName) throws Exception {
		ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
		String path = packageName.replace(".", "/");
		Enumeration<URL> resources = classLoader.getResources(path);

		List<File> dirs = new ArrayList<File>();

		while (resources.hasMoreElements()) {
			URL resource = resources.nextElement();
			dirs.add(new File(resource.getFile()));
		}

		List<Class> classes = new ArrayList<Class>();

		for (File directory : dirs) {
			classes.addAll(findClasses(directory, packageName));
		}

		return classes;
	}

	@SuppressWarnings("rawtypes")
	private static List<Class> findClasses(File directory, String packageName)
			throws ClassNotFoundException {
		List<Class> classes = new ArrayList<Class>();
		if (!directory.exists()) {
			return classes;
		}
		File[] files = directory.listFiles();
		for (File file : files) {
			if (file.isDirectory()) {
				assert !file.getName().contains(".");
				classes.addAll(findClasses(file,packageName + "." + file.getName()));
			} else if (file.getName().endsWith(".class")) {
				classes.add(Class.forName(packageName+ '.'+ file.getName().substring(0,file.getName().length() - 6)));
			}
		}
		return classes;
	}
	
	/**
	 * map转换成bean并赋值
	 * @param bean (new Bean())
	 * @param map
	 * @return  
	 * @throws SecurityException 
	 * @throws NoSuchMethodException 
	 * @throws InvocationTargetException 
	 * @throws IllegalArgumentException 
	 * @throws IllegalAccessException 
	 * @throws ReflectiveOperationException
	 */
	
	public static <T> T populate(T bean,Map<String, Object> map) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		
		if(bean==null||map==null){
			return bean;
		}
		
		//判断key中是否包含下划线,如果包含下划线,将进行处理
		wipeMapKeyLine(map);
		
		
		//获取bean的class类型
		Class<?> clazz= bean.getClass();
		
		
		//获取所有私有字段
		Field[] fields =	clazz.getDeclaredFields();
		
		for (Field field : fields) {
			String fieldName = field.getName();
			Object value = map.get(fieldName);
			
			//字段类型
			Class<?> fieldType = field.getType();
			
			//拼接set方法名
			String setMethod = "set"+firstUp(fieldName);
			//获取方法
			Method method = clazz.getMethod(setMethod, fieldType);
			//set方法不存在跳过
			if(method==null){
				continue;
			}

			method.invoke(bean, Convert(value, fieldType));
			
		}
		//log.debug("copy map ["+map+"] "+"to "+clazz);
		
		return (T)bean;
	}
	
	/**
	 * 把bean转换成map
	 * @param object
	 * @return
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 * @throws NoSuchMethodException
	 */
	public static Map<String, Object> beanToMap(Object object) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException{
		if(object==null||object.equals("")){
			return new LinkedHashMap<String, Object>();
		}
		
		//bean转换成map对象
		Map<String, String> map = BeanUtils.describe(object);
		
		//获取bean私有属性,便于排序
		Field[] fields = object.getClass().getDeclaredFields();
		
		//用于存放已经排序好的对象
		Map<String, Object> sortMap=new LinkedHashMap<String, Object>();
		
		//遍历排序
		for (Field field : fields) {
			String fieldName = field.getName();
			Object value = map.get(fieldName);
			sortMap.put(fieldName, value);
		}
		
		return sortMap;
	}
	
	
	public static void  wipeMapKeyLine(Map<String, Object> map){
		//获取所有的map字段
		List<String> colunms = new ArrayList<String>(map.keySet());
		

		//遍历字段
		for (int k = 0; k < colunms.size(); k++) {
			String colunm=colunms.get(k);
				//判断字段是否包含_
			if(colunm.contains("_")){
				//切分
				String[] split = colunm.split("_");
						
				//字段的首字母不需要大写
				String fieldName=split[0];
						
				//从第二个字段开始首字母大写,并拼接
				for (int i = 1; i < split.length; i++) {
					fieldName+=firstUp(split[i]);
				}
						
				//获取colunm的值
				Object value = map.get(colunm);
						
				//将处理好的字段作为key,put上去
				map.put(fieldName, value);
					
				//移除原有的key
				map.remove(colunm);
			}
		}
	}
	
	
	/**
	 * 首字母大写
	 * @param str
	 * @return
	 */
	public static String firstUp(String str){
		
		if(str==null){
			return null;
		}
		if(str.equals("")){
			return "";
		}
		
		if(str.length()==1){
			return str.toUpperCase();
		}
		
		
		String first = str.substring(0,1).toUpperCase();
		String last = str.substring(1);
		
		return first+last;
	}
	
	public static Object Convert(Object obj,Class<?> type){
		
		if(obj==null||type==null){
			return null;
		}

		if(Integer.class.isAssignableFrom(type)){
			return Integer.parseInt(obj.toString());
		}
		if(Long.class.isAssignableFrom(type)){
			return Long.parseLong(obj.toString());
		}
		if(String.class.isAssignableFrom(type)){
			return obj.toString();
		}
		if(Float.class.isAssignableFrom(type)){
			return Float.parseFloat(obj.toString());
		}
		if(BigDecimal.class.isAssignableFrom(type)){
			return new BigDecimal(obj.toString());
		}
		if(Double.class.isAssignableFrom(type)){
			return Double.parseDouble(obj.toString());
		}
		if(Byte.class.isAssignableFrom(type)){
			return Byte.parseByte(obj.toString());
		}
		return obj;
		
	}
	
	
	/**
	 * 方法依赖value 类型, 来确定要创建的字段类型
	 * @param map
	 * @return
	 * @throws CannotCompileException
	 * @throws NotFoundException
	 */
	public  static Class<?> dyCreateClass(String className,Map<String,Class<?>> map) throws CannotCompileException, NotFoundException {
		
		if(map==null){
			return null;
		}
		
		// 动态创建类
		ClassPool ctPool = ClassPool.getDefault();

		// 创建类的路径
		CtClass ctClass = ctPool.makeClass(className);
		
		//获取所有字段
		Set<String> fields = map.keySet();
		
		for (String filed : fields) {
			//获取map值
			Class<?> value = map.get(filed);
			//以value值来确定要创建的字段类型
			CtClass fieldClass = ctPool.get(value.getName());
			CtField ctField = new CtField(fieldClass,filed, ctClass);
			ctField.setModifiers(Modifier.PRIVATE);
			ctClass.addField(ctField);
			
			// 动态创建get/set方法
			ctClass.addMethod(CtNewMethod.setter("set" + firstUp(filed), ctField));
			ctClass.addMethod(CtNewMethod.getter("get" + firstUp(filed), ctField));
		}
		

		// 创建构造方法
		CtConstructor constructor = new CtConstructor(null, ctClass);
		constructor.setModifiers(Modifier.PUBLIC);
		constructor.setBody("{}");
		ctClass.addConstructor(constructor);

			// 转换成class
		Class<?> clazz = ctClass.toClass();
		return clazz;
	}
}